home *** CD-ROM | disk | FTP | other *** search
/ Amiga Magazin: Amiga-CD 1996 March / Amiga-CD 1996 #3.iso / pd-software / mui_3.1 / developer / extclasses / mcc_userdata / muiclassheader.c < prev    next >
C/C++ Source or Header  |  1996-01-19  |  11KB  |  395 lines

  1. /*
  2.   MuiClassHeader.c    Universal header file MUI custom classes     V1.0
  3.   Copyright(C) 1994     Jochen Wiedmann
  4.  
  5.   Computer: Amiga 1200
  6.   Compiler: Dice 3.01
  7.  
  8.   Author:     Jochen Wiedmann
  9.           Am Eisteich 9
  10.           72555 Metzingen
  11.           Germany
  12.           Phone: 07123 / 14881
  13.           Internet: wiedmann@zdv.uni-tuebingen.de
  14.  
  15.   This code implements the usual startup code of a MUI custom class.
  16.   I recommend reading Appendix C (Sample Library Source Code) of the
  17.   RKM: Libraries, Third Edition for a complete understanding of the
  18.   following. Another good choice would be the shared library example
  19.   of the Dice distribution.
  20.  
  21.   Your library should be implmented in another file. You must define the
  22.   following preprocessor symbols with compiler options, when this file
  23.   is compiled:
  24.     LIBNAME:     Name of this library, "chess.library" for example
  25.     LIBVERSION:  Library version, "40" for example
  26.     LIBREVISION: Library revision, "1" for example
  27.     LIBINITFUNC: The name of the initialization function. Will be called
  28.          with the library base pointer in register a6,
  29.          should return 0 for success, nonzero otherwise.
  30.     LIBTERMFUNC: The name of a function called when the class will be
  31.          removed from the system; will receive the library base
  32.          pointer in register a6.
  33.  
  34.   The following preprocessor symbols may be defined, but don't need to:
  35.     LIBOPENFUNC:  Function to be called every time the library is opened.
  36.           Does not make much sense in most cases. (Default is no
  37.           library specific stuff.)
  38.     LIBCLOSEFUNC: Function to be called every time when CloseLibrary() is
  39.           executed. This is the opponent to LIBCLOSEFUNC and does
  40.           not make much sense in most cases either. (Default is no
  41.           library specific stuff.)
  42.     LIBBASESIZE:  Size of the library base, "sizeof(struct Library)" for
  43.           example. (This is the default, if LIBBASESIZE isn't
  44.           defined.
  45.  
  46.  
  47.  
  48.  
  49.   WARNINGS - WARNINGS - WARNINGS - WARNINGS - WARNINGS - WARNINGS - WARNINGS
  50.     - This code depends heavily on some assumptions which are fulfilled
  51.       by Dice:
  52.     * All data declared as "const" will go to the code segment
  53.     * The compiler doesn't rearrange the order of the data and code
  54.       items.
  55.     - You may use uninialized data items in your library code. However,
  56.       the startup code will *not* clear the BSS segment. This means
  57.       that you must not depend on an uninitialized variable being zero!
  58.     - You may use the data and bss segment as usual. But remember that
  59.       this data will be global to the library and hence shared by all
  60.       users of the library. And don't forget to recreate the a4 register,
  61.       if you use such data items! (Usually by adding __saveds or
  62.       something similar to your functions.)
  63.  
  64.   EXAMPLE: To create the header of "userdata.mcc", version 40.1 with library
  65.   specific routines InitUserdata and TermUserdata, and a "struct
  66.   UserdataBase" as library base you would do the following:
  67.  
  68.     dcc -DLIBNAME=userdata.mcc -DLIBVERSION=40 -DLIBREVISION=1
  69.     -DLIBINITFUNC=InitUserdata -DLIBTERMFUNC=TermUserdata
  70.     "-DLIBBASESIZE=sizeof(struct UserdataBase)" -c Userdata.c
  71. */
  72.  
  73.  
  74.  
  75.  
  76.  
  77. /****************************************************************************
  78.   Include files
  79. ****************************************************************************/
  80. #ifndef EXEC_TYPES_H
  81. #include <exec/types.h>
  82. #endif
  83. #ifndef EXEC_NODES_H
  84. #include <exec/nodes.h>
  85. #endif
  86. #ifndef EXEC_RESIDENT_H
  87. #include <exec/resident.h>
  88. #endif
  89. #ifndef EXEC_LIBRARIES_H
  90. #include <exec/libraries.h>
  91. #endif
  92. #ifndef EXEC_INITIALIZERS_H
  93. #include <exec/initializers.h>
  94. #endif
  95. #ifndef DOS_DOS_H
  96. #include <dos/dos.h>
  97. #endif
  98. #ifndef CLIB_EXEC_PROTOS_H
  99. #include <clib/exec_protos.h>
  100. #endif
  101. #ifndef PRAGMAS_EXEC_PRAGMAS_H
  102. #include <pragmas/exec_pragmas.h>
  103. #endif
  104.  
  105.  
  106.  
  107.  
  108.  
  109. /*****************************************************************************
  110.   Compiler specific stuff (Handling register arguments)
  111. *****************************************************************************/
  112. #if defined(_DCC)
  113. #define REG(x) __ ## x
  114. #define SAVEDS __geta4
  115. #define ASM
  116. #define REGARGS __regargs
  117. #else
  118. #if defined(__SASC)
  119. #define REG(x) register __ ## x
  120. #define SAVEDS __saveds
  121. #define ASM __asm
  122. #define REGARGS __regargs
  123. #else
  124. #error "Don't know how to handle register arguments for your compiler."
  125. #endif
  126. #endif
  127.  
  128.  
  129.  
  130. /*
  131.   This routine is an entry point if anyone might wish to run the library
  132.   as an executable.
  133. */
  134. STATIC LONG DummyStart(VOID){return(-1);}
  135.  
  136.  
  137.  
  138.  
  139.  
  140.  
  141. /****************************************************************************
  142.   Library name, ID and version string
  143. ****************************************************************************/
  144. #define S(x) #x
  145. const STATIC UBYTE LibName [] = S(LIBNAME);
  146. const STATIC UBYTE IdString [] = S(LIBNAME) " " S(LIBVERSION) "." \
  147.        S(LIBREVISION) " (" __DATE__ ")\r\n";
  148. extern const UBYTE VersionTag [];
  149.  
  150.  
  151.  
  152.  
  153.  
  154.  
  155. /*****************************************************************************
  156.   The following table is used to initialize the library base. See
  157.   exec.library/InitStruct() and "exec/initializers.i" for details.
  158. *****************************************************************************/
  159. const STATIC UWORD DataTable[] =  { 0xa000 + (int) OFFSET(Node, ln_Type),
  160.                       NT_LIBRARY << 8,
  161.                     0x8000 + (int) OFFSET(Node, ln_Name)
  162.                   };
  163. const STATIC ULONG DataTable1[] = { (ULONG) LibName };
  164. const STATIC UWORD DataTable2[] = { 0xa000 + (int) OFFSET(Library, lib_Flags),
  165.                       (LIBF_SUMUSED|LIBF_CHANGED) << 8,
  166.                     0x9000 + (int) OFFSET(Library, lib_Version),
  167.                       LIBVERSION,
  168.                     0x9000 + (int) OFFSET(Library, lib_Revision),
  169.                       LIBREVISION,
  170.                     0x8000 + (int) OFFSET(Library, lib_IdString)
  171.                   };
  172. const STATIC ULONG DataTable3[] = { (ULONG) IdString,
  173.                     0
  174.                   };
  175.  
  176.  
  177.  
  178.  
  179.  
  180.  
  181. /****************************************************************************
  182.   The following table is expected to be at the beginning of any library.
  183. ****************************************************************************/
  184. extern APTR InitTable [];
  185. const STATIC struct Resident RomTag =
  186. {
  187.   RTC_MATCHWORD, /* ILLEGAL instruction, magic cookie to identify Resident
  188.             structure */
  189.   &RomTag,     /* Additional legality check */
  190.   &RomTag,     /* Where to continue looking for Resident structures */
  191.   RTF_AUTOINIT,  /* Easy initialization */
  192.   LIBVERSION,     /* Library version */
  193.   NT_LIBRARY,     /* type of module */
  194.   0,         /* Priority, don't use */
  195.   LibName,     /* library name */
  196.   IdString,     /* Id string */
  197.   InitTable     /* See below */
  198. };
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205. /*****************************************************************************
  206.   The following function will be called at startup.
  207.  
  208.   Inputs: LibPtr - pointer to the library base, initialized due to the
  209.            specifications in DataTable
  210.       SegList - BPTR to the segment list
  211.       _SysBase - the usual ExecBase pointer
  212.  
  213.   Result: LibPtr, if all was okay and the library may be linked into the
  214.       system library list. NULL otherwise
  215. *****************************************************************************/
  216. STATIC BPTR MySegList;
  217. SAVEDS ASM struct Library *_LibInit(REG(d0) struct Library *LibPtr,
  218.                     REG(a0) BPTR SegList,
  219.                     REG(a6) struct ExecBase *_SysBase)
  220.  
  221. {
  222.   extern ULONG LIBINITFUNC(REG(a6) struct Library *);
  223.  
  224.   MySegList = SegList;
  225.   if (LIBINITFUNC(LibPtr))
  226.     {
  227.       return((BPTR) NULL);
  228.     }
  229.   return(LibPtr);
  230. }
  231.  
  232.  
  233.  
  234.  
  235.  
  236.  
  237.  
  238.  
  239.  
  240.  
  241.  
  242.  
  243.  
  244.  
  245.  
  246. /****************************************************************************
  247.   The following functions are called from exec.library/OpenLibrary(),
  248.   exec.library/CloseLibrary() and exec.library/ExpungeLibrary(),
  249.   respectively.
  250.  
  251.   Exec puts the library base pointer in a6 and turns off task switching
  252.   while they are executed, so we should not wait too long inside.
  253. ****************************************************************************/
  254.  
  255. /*
  256.   This function is called from exec.library/OpenLibrary().
  257.  
  258.   Inputs: LibPtr - pointer to the library base
  259.       Version - the suggested version number
  260.  
  261.   Result: LibPtr, if successful, NULL otherwise
  262. */
  263. ASM struct Library *_LibOpen(REG(a6) struct Library *LibPtr,
  264.                  REG(d0) ULONG Version)
  265. {
  266. #ifdef LIBOPENFUNC
  267.   extern ULONG LIBOPENFUNC(REG(a6) struct Library *);
  268. #endif
  269.  
  270.   ++LibPtr->lib_OpenCnt;
  271.   LibPtr->lib_Flags &= ~LIBF_DELEXP; /* Prevent delayed expunge */
  272.  
  273.   /* Library specific initialization */
  274. #ifdef LIBOPENFUNC
  275.   extern ULONG LIBOPENFUNC(LibPtr);
  276. #endif
  277.  
  278.   return(LibPtr);
  279. }
  280.  
  281.  
  282.  
  283.  
  284. /*
  285.   This function is called from exec.library/RemoveLibrary().
  286.  
  287.   Inputs: LibPtr - pointer to the library base.
  288.  
  289.   Result: Segment list of the library (see arguments of _LibInit()),
  290.       if the library isn't opened currently, NULL otherwise.
  291. */
  292. extern struct Library *SysBase;
  293. SAVEDS ASM BPTR _LibExpunge(REG(a6) struct Library *LibPtr)
  294.  
  295. {
  296.   extern VOID LIBTERMFUNC(REG(a6) struct Library *);
  297.  
  298.   if (LibPtr->lib_OpenCnt)
  299.     { LibPtr->lib_Flags |= LIBF_DELEXP;
  300.       return((BPTR) NULL);
  301.     }
  302.  
  303.   /* Library specific cleanup. */
  304.   LIBTERMFUNC(LibPtr);
  305.  
  306.   /* Remove the library from the library list. */
  307.   Remove((struct Node *) LibPtr);
  308.  
  309.   return(MySegList);
  310. }
  311.  
  312.  
  313.  
  314.  
  315.  
  316. /*
  317.   This function is called from exec/CloseLibrary().
  318.  
  319.   Inputs: LibPtr - pointer to the library base as returned from
  320.            OpenLibrary().
  321.  
  322.   Result: Segment list of the library (see arguments of _LibInit), if there
  323.       was a delayed expunge and the library is no longer open, NULL
  324.       otherwise.
  325. */
  326. ASM BPTR _LibClose(REG(a6) struct Library *LibPtr)
  327.  
  328. {
  329. #ifdef LIBCLOSEFUNC
  330.   extern VOID LIBCLOSEFUNC(REG(a6) struct Library *);
  331.  
  332.   LIBCLOSEFUNC(LibPtr);
  333. #endif
  334.  
  335.   if (!(--LibPtr->lib_OpenCnt)  &&  (LibPtr->lib_Flags & LIBF_DELEXP))
  336.     { return(_LibExpunge(LibPtr));
  337.     }
  338.   return((BPTR) NULL);
  339. }
  340.  
  341.  
  342.  
  343.  
  344.  
  345. /*
  346.   Dummy function to return 0.
  347. */
  348. ULONG _LibNull(VOID)
  349.  
  350. {
  351.   return(0);
  352. }
  353.  
  354.  
  355.  
  356.  
  357.  
  358. /****************************************************************************
  359.   Table of functions included in this library; the first 4 are the same
  360.   for any library and for internal use only, MCC_GetClass is the only
  361.   public function of any MUI custom class.
  362. ****************************************************************************/
  363. extern REGARGS VOID MCC_GetClass(VOID);
  364.  
  365. const STATIC APTR LibFuncTable[] =
  366.   {
  367.     _LibOpen,
  368.     _LibClose,
  369.     _LibExpunge,
  370.     _LibNull,
  371.     MCC_GetClass,
  372.     (APTR)-1
  373.   };
  374.  
  375.  
  376.  
  377.  
  378.  
  379.  
  380. /****************************************************************************
  381.   The romtag specified that we were RTF_AUTOINIT. This means that rt_Init
  382.   points to the table below. (Without RTF_AUTOINIT it would point to a
  383.   routine to run.)
  384. ****************************************************************************/
  385. #ifndef LIBBASESIZE
  386. #define LIBBASESIZE sizeof(struct Library)
  387. #endif
  388. const APTR InitTable[4] =
  389. {
  390.   (APTR)LIBBASESIZE,  /* size of library base */
  391.   (APTR)LibFuncTable, /* library function table */
  392.   (APTR)DataTable,    /* library base initialization table */
  393.   (APTR)_LibInit,      /* function to call on startup */
  394. };
  395.